package com.csii.modules.online.diagram.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.*;

import javax.annotation.Resource;

import com.csii.core.api.Result;
import com.csii.modules.online.diagram.entity.ChartsData;
import com.csii.modules.online.diagram.entity.CommonConstants;
import com.csii.modules.online.diagram.entity.DiagramConfiguration;
import com.csii.modules.online.diagram.entity.DiagramFieldConfiguration;
import com.csii.modules.online.diagram.mapper.DiagramConfigurationMapper;
import com.csii.modules.online.diagram.service.IDiagramConfigurationService;
import com.csii.modules.system.util.OnlineUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * @Description: 图表配置
 */
@Service
public class DiagramConfigurationServiceImpl extends ServiceImpl<DiagramConfigurationMapper, DiagramConfiguration>
		implements IDiagramConfigurationService {

	@Autowired
	private DiagramFieldConfigurationServiceImpl diagramFieldConfigurationService;
	@Resource
	private DiagramConfigurationMapper diagramConfigurationMapper;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void add(DiagramConfiguration diagramConfiguration) {
		// 保存主表信息
		this.save(diagramConfiguration);
		// 保存子表信息
		if (diagramConfiguration != null && diagramConfiguration.getDiagramFieldConfigurationList() != null
				&& !diagramConfiguration.getDiagramFieldConfigurationList().isEmpty()) {
			diagramConfiguration.getDiagramFieldConfigurationList()
					.forEach(dfc -> dfc.setDiagramCode(diagramConfiguration.getCode()));
			this.diagramFieldConfigurationService.saveBatch(diagramConfiguration.getDiagramFieldConfigurationList());
		}

	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void edit(DiagramConfiguration diagramConfiguration) {
		this.updateById(diagramConfiguration);
		// 更新子表信息
		Map<String, Object> columnMap = new HashMap<>();
		columnMap.put("DIAGRAM_CODE", diagramConfiguration.getCode());
		this.diagramFieldConfigurationService.removeByMap(columnMap);
		this.diagramFieldConfigurationService.saveBatch(diagramConfiguration.getDiagramFieldConfigurationList());

	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteById(String id) {
		DiagramConfiguration diagramConfiguration = super.getById(id);
		this.removeById(id);
		// 删除子表信息
		Map<String, Object> columnMap = new HashMap<>();
		columnMap.put("DIAGRAM_CODE", diagramConfiguration.getCode());
		this.diagramFieldConfigurationService.removeByMap(columnMap);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteBatch(String ids) {
		List<String> idList = Arrays.asList(ids.split(","));
		QueryWrapper<DiagramConfiguration> queryWrapper = new QueryWrapper<>();
		queryWrapper.in("ID", idList);
		List<DiagramConfiguration> diagramConfigurationList = super.list(queryWrapper);
		this.removeByIds(idList);
		// 删除子表信息
		if (diagramConfigurationList != null && !diagramConfigurationList.isEmpty()) {
			Map<String, Object> columnMap = new HashMap<>();
			for (DiagramConfiguration diagramConfiguration : diagramConfigurationList) {
				columnMap.clear();
				columnMap.put("DIAGRAM_CODE", diagramConfiguration.getCode());
				this.diagramFieldConfigurationService.removeByMap(columnMap);
			}
		}
	}

	@Override
	public List selectBySql(String sql) {
		return null;//代码扫描-sql注入 this.diagramConfigurationMapper.selectBySql(sql);
	}

	@Override
	public ChartsData<Object, DiagramConfiguration, DiagramFieldConfiguration> getChartsData(String code){
		DiagramConfiguration diagramConfiguration = getOne(new QueryWrapper<DiagramConfiguration>().eq("code", code));
		if (diagramConfiguration == null) {
			return null;
		}
		// 根据sql查询数据
		List dataList = new ArrayList<Map<String, Object>>();
		//如果是sql，查询相关表
		if (CommonConstants.DATA_TYPE_SQL.equals(diagramConfiguration.getDataType())) {
			dataList=selectBySql(diagramConfiguration.getCgrSql());
		}
		//查询字段
		List<DiagramFieldConfiguration> diagramFieldConfigurationList = this.diagramFieldConfigurationService
				.list(new QueryWrapper<DiagramFieldConfiguration>().eq("diagram_code", code));
		Map<String, Expression> expressions = new HashMap<>();
		Map<String, String> aggregates = new HashMap<>();
		Map<Object,Map<String, Object>> aggregateDataMap = new HashMap<Object,Map<String, Object>>();
		String xField = diagramConfiguration.getXaxisField();
		String[] yFields = diagramConfiguration.getYaxisField().split(",");
		diagramConfiguration.setGroupField(diagramConfiguration.getYaxisField());
		for(DiagramFieldConfiguration dfc : diagramFieldConfigurationList){
			//如果是功能函数，存储函数
			if(StringUtils.isNotEmpty(dfc.getFunc())){
				String expression = dfc.getFunc();
				Expression compiledExp = new SpelExpressionParser().parseExpression(expression);
				expressions.put(dfc.getFieldName(), compiledExp);
			}
			if(ArrayUtils.contains(yFields, dfc.getFieldName())){
					aggregates.put(dfc.getFieldName(), dfc.getFieldTxt());
			}
		}
		if(expressions.size()>0 || aggregates.size()>0){
			for(Object data : dataList){
				EvaluationContext context= new StandardEvaluationContext(data);
				for(Map.Entry<String, Expression> entry : expressions.entrySet()){
					Map<String,Object> env = new HashMap<String,Object>();
					env.putAll((Map<String,Object>) data);
					((Map<String,Object>) data).put(entry.getKey(), entry.getValue().getValue(context));
				}
				if(diagramConfiguration.getAggregate()){
					Object xValue = ((Map) data).get(xField);
					if(aggregateDataMap.get(xValue) == null){
						Map<String, Object> aggregateData = new HashMap<>();
						aggregateData.put(xField, xValue);
						for(Map.Entry<String, String> yField : aggregates.entrySet()){
							aggregateData.put(yField.getKey(), BigDecimal.ZERO);
						}
						aggregateDataMap.put(xValue, aggregateData);
					}

					Map<String, Object> aggregateData = aggregateDataMap.get(xValue);
					for(Map.Entry<String, String> yField : aggregates.entrySet()){
						aggregateData.put(yField.getKey(), OnlineUtil.calculation(aggregateData.get(yField.getKey()), ((Map) data).get(yField.getKey()), yField.getValue()));
					}
					aggregateDataMap.put(xValue, aggregateData);
				}
			}
		}
		Map<String, Collection> result = new HashMap<String, Collection>();
		result.put("data", dataList);
		result.put("aggregate", aggregateDataMap.values());
		// 封装数据
		ChartsData<Object, DiagramConfiguration, DiagramFieldConfiguration> chartsData = new ChartsData<>();
		chartsData.setData(result);
		chartsData.setDictOptions(null);
		chartsData.setHead(diagramConfiguration);
		chartsData.setItems(diagramFieldConfigurationList);
		return chartsData;
	}
}
